using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Collections;
using System.Threading;

namespace TPDSConfig
{
    public class Utils
    {
        /// <summary>
        /// Loads the file. DB 25/01/11: Changed to return null if unable to read file, instead of throwing exception which is 
        /// later caught and reported again.
        /// </summary>
        public static object LoadXML(string filepath, Type filetype)
        {
            if( String.IsNullOrEmpty( filepath ) )
                return null;

            FileStream fs = null;
            try
            {
                // Try to access the file, waiting until we can or timeout.
                fs = WaitForFile( filepath, FileMode.Open, FileAccess.Read );
                if( fs == null )
                    throw new TimeoutException( "Unable to open file " + filepath + ". Timed out." );

                XmlSerializer xs = new XmlSerializer(filetype);
                object xmlfile = xs.Deserialize(fs);
                return xmlfile;
            }
            catch (Exception Ex)
            {
                ErrorLog.WriteError(Ex.Message, filepath);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose( );
                    fs = null;
                }
            }

            // Returns null if unsuccessful
            return null;
        }

        public static void SaveXML(string filepath, Type filetype, object objecttoserialize)
        {
            if( String.IsNullOrEmpty( filepath ) )
                return;

            FileStream fs = null; 
            try
            {
                // Try to access the file, waiting until we can or timeout.
                fs = WaitForFile( filepath, FileMode.OpenOrCreate, FileAccess.ReadWrite );
                if( fs == null )
                    throw new TimeoutException( "Unable to save file " + filepath + ". Timed out." );

                fs.SetLength(0);
                XmlSerializer xs = new XmlSerializer(filetype);
                xs.Serialize(fs, objecttoserialize);
            }
            catch (Exception ex)
            {
                ErrorLog.WriteError(ex.Message, filepath);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose( );
                    fs = null;
                }
            }
        }

        /// <summary>
        /// Tries to access file based on requested mode. DB 24/01/11: There are problems with this code as it originally released the file
        /// handle, which allowed other processes to immediately access the file. Hence have changed the code to return the file handle, 
        /// which means the calling code MUST release the handle.
        /// </summary>
        private static FileStream WaitForFile( string filepath, FileMode mode, FileAccess access )
        {
            int maxWait = 30;
            int count = 0;

            // This is what we now return...
            FileStream fs = null;

            while (count < maxWait)
            {
                try
                {
                    fs = new FileStream( filepath, mode, access );
                    break;
                }
                catch
                {
                    count += 1;
                    Thread.Sleep(1000);
                }
            }

            return fs;
        }


        public class FileInfoComparer : IComparer<FileInfo>
        {
            public int Compare(FileInfo x, FileInfo y)
            {
                CaseInsensitiveComparer comparer = new CaseInsensitiveComparer();
                return comparer.Compare(x.Name, y.Name);
            }
        }
    }
}
